//
//  DerbyNSOdePeer.m
//  DerbyOSSampler
//
//  Created by glenn andreas on 1/6/14.
//  Copyright (c) 2014 glenn andreas. All rights reserved.
//

#import "DerbyNSOdePeer.h"
#import "DerbyNSOde.h"
#import "DerbyNSOdeResolver.h"
#import "DerbyNSOdeAddress.h"

@interface DerbyNSOdePeer()
@property (assign) void *ctx;
@property (assign) void *mailbox;
@property (assign, readwrite) BOOL connected;
@property (assign, readwrite) BOOL ready;
@end
@implementation DerbyNSOdePeer
- (void) dealloc
{
    zmq_close(_mailbox);
}
- (id) initWithContext: (void *) ctx address: (DerbyNSOdeAddress *) address uuid: (NSString *) uuid
{
    self = [super init];
    if (self) {
        _ctx = ctx;
        _address = address;
        _uuid = uuid;
        _connected = false;
        _serviceName = @"???";
        _mailbox = NULL;
    }
    return self;
}
- (id) initWithContext: (void *) ctx address: (DerbyNSOdeAddress *) address;
{
    return [self initWithContext: ctx address: address uuid: nil];
}
- (NSData *) uuidBytes
{
    CFUUIDBytes bytes;
    CFUUIDRef uuid = CFUUIDCreateFromString(kCFAllocatorDefault, (__bridge CFStringRef)self.uuid);
    bytes = CFUUIDGetUUIDBytes(uuid);
    CFRelease(uuid);
    return [NSData dataWithBytes:&bytes length:sizeof(bytes)];
}
- (BOOL) connect: (NSError **) error
{
    if (self.connected)
        return YES;
    // Create new outgoing socket (drop any messages in transit)
    self.mailbox = zmq_socket(self.ctx, ZMQ_DEALER);
// Set our caller 'From' identity so that receiving node knows
// who each message came from.
    NSData *uuidbytes = self.uuidBytes;
    zmq_setsockopt(self.mailbox, ZMQ_IDENTITY, uuidbytes.bytes, uuidbytes.length);
// Set a high-water mark that allows for reasonable activity
    int value = 1000;
    zmq_setsockopt(self.mailbox, ZMQ_SNDHWM, &value, sizeof(int));
// Send messages immediately or return EAGAIN
    value = 0;
    zmq_setsockopt(self.mailbox, ZMQ_SNDTIMEO, &value, sizeof(int));
// Connect through to peer node
//#print("tcp://%s" %endpoint)
    NSString *addr = [NSString stringWithFormat:@"tcp://%@", self.address.stringValue];
    zmq_connect(self.mailbox, addr.UTF8String);
    self.connected = YES;
    self.ready = NO;
    if (!self.uuid)
        self.uuid = @"???";
// send the "i am" message
    [self tellPeer:DerbyNSOdeHELO body:self.address.stringValue];
    return YES;
}
- (void) disconnect
{
    if (!self.connected) {
        zmq_close(self.mailbox);
        self.mailbox = NULL;
        self.connected = NO;
    }
}
- (NSString *) description
{
    return [NSString stringWithFormat:@"<NSOdePeer %@/%@ %@>",self.uuid, self.serviceName, self.address.stringValue];
}
- (void) tellPeer: (NSString *) msg body: (NSString *) body
{
    if (!self.connected)
        return;
// Send a message (as a UTF8 unicode string) to a given peers
//  UUID already sent
    zmq_send(self.mailbox, msg.UTF8String, strlen(msg.UTF8String), ZMQ_SNDMORE);
    zmq_send(self.mailbox, body.UTF8String, strlen(body.UTF8String), 0);
//        peerLogger.debug("%s: Telling peer %s %s",self,msg,body)
}
@end
